package com.gosophia.oa.test;

import com.thoughtworks.selenium.SeleneseTestBase;
import com.thoughtworks.selenium.SeleneseTestCase;
import com.thoughtworks.selenium.Selenium;

public class CustomSeleneseTestCase extends SeleneseTestCase {

    private CustomSeleneseTestBase stb = new CustomSeleneseTestBase();
    
    /** Use this object to run all of your selenium tests */
    protected Selenium selenium;
    
    public CustomSeleneseTestCase() {
        super();
    }

    
    public CustomSeleneseTestCase(String name) {
        super(name);
    }
    
    /** Asserts that there were no verification errors during the current test, failing immediately if any are found */
    public void checkForVerificationErrors() {
        stb.checkForVerificationErrors();
    }
    
    /** Clears out the list of verification errors */
    public void clearVerificationErrors() {
        stb.clearVerificationErrors();
    }
    
    /** Returns the body text of the current page */
    public String getText() {
        return stb.getText();
    }
    
    /** Sleeps for the specified number of milliseconds */
    public void pause(int millisecs) {
        stb.pause(millisecs);
    }
    
    /** Calls this.setUp(null)
     * @see #setUp(String)
     */
    public void setUp() throws Exception {
        stb.setUp();
        selenium = stb.selenium;
    }
    
    /**
     * Calls this.setUp with the specified url and a default browser.  On Windows, the default browser is *iexplore; otherwise, the default browser is *firefox.
     * @see #setUp(String, String)
     * @param url the baseUrl to use for your Selenium tests
     * @throws Exception
     * 
     */
    public void setUp(String url) throws Exception {
        stb.setUp(url);
        selenium = stb.selenium;
    }
    
    /**
     * Creates a new DefaultSelenium object and starts it using the specified baseUrl and browser string
     * @param url the baseUrl for your tests
     * @param browserString the browser to use, e.g. *firefox
     * @throws Exception
     */
    public void setUp(String url, String browserString) throws Exception {
        stb.setUp(url, browserString);
        selenium = stb.selenium;
    }
    
    /** checks for verification errors and stops the browser */
    public void tearDown() throws Exception {
        stb.tearDown();
    }
    
    /** Like assertEquals, but fails at the end of the test (during tearDown) */
    public void verifyEquals(boolean arg1, boolean arg2) {
        stb.verifyEquals(arg1, arg2);
    }
    
    /** Like assertEquals, but fails at the end of the test (during tearDown) */
    public void verifyEquals(Object s1, Object s2) {
        stb.verifyEquals(s1, s2);
    }
    
    /** Like assertEquals, but fails at the end of the test (during tearDown) */
    public void verifyEquals(String[] s1, String[] s2) {
        stb.verifyEquals(s1, s2);
    }
    
    /** Like assertFalse, but fails at the end of the test (during tearDown) */
    public void verifyFalse(boolean b) {
        stb.verifyFalse(b);
    }
    
    /** Like assertNotEquals, but fails at the end of the test (during tearDown) */
    public void verifyNotEquals(boolean s1, boolean s2) {
        stb.verifyNotEquals(s1, s2);
    }
    
    /** Like assertNotEquals, but fails at the end of the test (during tearDown) */
    public void verifyNotEquals(Object s1, Object s2) {
        stb.verifyNotEquals(s1, s2);
    }
    
    /** Like assertTrue, but fails at the end of the test (during tearDown) */
    public void verifyTrue(boolean b) {
        stb.verifyTrue(b, null);
    }
    public void verifyTrue(boolean b, String message) {
        stb.verifyTrue(b, message);
    }

    /** Like JUnit's Assert.assertEquals, but knows how to compare string arrays */
    public static void assertEquals(Object s1, Object s2) {
        SeleneseTestBase.assertEquals(s1, s2);
    }
    
    /** Like JUnit's Assert.assertEquals, but handles "regexp:" strings like HTML Selenese */
    public static void assertEquals(String s1, String s2) {
        SeleneseTestBase.assertEquals(s1, s2);
    }
    
    /** Like JUnit's Assert.assertEquals, but joins the string array with commas, and 
     * handles "regexp:" strings like HTML Selenese
     */
    public static void assertEquals(String s1, String[] s2) {
        SeleneseTestBase.assertEquals(s1, s2);
    }
    
    /** Asserts that two string arrays have identical string contents */
    public static void assertEquals(String[] s1, String[] s2) {
        SeleneseTestBase.assertEquals(s1, s2);
    }
    
    /** Asserts that two booleans are not the same */
    public static void assertNotEquals(boolean b1, boolean b2) {
        SeleneseTestBase.assertNotEquals(b1, b2);
    }
    
    /** Asserts that two objects are not the same (compares using .equals()) */
    public static void assertNotEquals(Object obj1, Object obj2) {
        SeleneseTestBase.assertNotEquals(obj1, obj2);
    }
    
    /** Compares two objects, but handles "regexp:" strings like HTML Selenese
     * @see #seleniumEquals(String, String)
     * @return true if actual matches the expectedPattern, or false otherwise
     */
    public static boolean seleniumEquals(Object expected, Object actual) {
        return SeleneseTestBase.seleniumEquals(expected, actual);
    }
    
    /** Compares two strings, but handles "regexp:" strings like HTML Selenese
     * 
     * @param expectedPattern
     * @param actual
     * @return true if actual matches the expectedPattern, or false otherwise
     */
    public static boolean seleniumEquals(String expected, String actual) {
        return SeleneseTestBase.seleniumEquals(expected, actual);
    }
    
    
    /**
     * @deprecated Use {@link #isCaptureScreenShotOnFailure()} instead
     */
    protected boolean isCaptureScreetShotOnFailure() {
        return isCaptureScreenShotOnFailure();
    }


    protected boolean isCaptureScreenShotOnFailure() {
        return stb.isCaptureScreenShotOnFailure();
    }
    
    protected String runtimeBrowserString() {
        return stb.runtimeBrowserString();
    }
    
    /**
     * @deprecated Use {@link #setCaptureScreenShotOnFailure(boolean)} instead
     */
    protected void setCaptureScreetShotOnFailure(boolean b) {
        setCaptureScreenShotOnFailure(b);
    }


    protected void setCaptureScreenShotOnFailure(boolean b) {
        stb.setCaptureScreenShotOnFailure(b);
    }
    
    protected void setTestContext() {
        selenium.setContext(this.getClass().getSimpleName() + "." + getName());
    }
    
    /**
     * Runs the bare test sequence, capturing a screenshot if a test fails
     * @exception Throwable if any exception is thrown
     */
    // @Override
    public void runBare() throws Throwable {
        if (!isCaptureScreenShotOnFailure()) {
            super.runBare();
            return;
        }
        setUp();
        try {
            runTest();
        } catch (Throwable t) {
            if (selenium != null) {
                String filename = getName() + ".png";
                try {
                    selenium.captureScreenshot(filename);
                    System.err.println("Saved screenshot " + filename);
                } catch (Exception e) {
                    System.err.println("Couldn't save screenshot " + filename + ": " + e.getMessage());
                    e.printStackTrace();
                }
                throw t;
            }
        }
        finally {
            tearDown();
        }
    }

    public String join(String[] array, char c) {
        return CustomSeleneseTestBase.join(array, c);
    }
    
    
    /**
     * 将输入文字转换为glog模式，以匹配页面上文字间的多余空格
     * @param text 要匹配的文字
     * @return 转换后的glob模式字符串
     */
    protected String convertToGlobbingPattern(String text) {
    	if(text == null) return null;
    	if(text == "") return "";
    	
    	if(text.startsWith("glob:")
    			|| text.startsWith("regex:")) 
    		return text;
    	
    	StringBuilder sb = new StringBuilder("glob:");
    	for(int i = 0; i < text.length(); i++) {
    		sb.append(text.charAt(i)).append("*");
    	}
    	return sb.substring(0, sb.length()-1);
    }
    
    /**
     * 将输入文字转换为可匹配中间空格的正则表达式
     * @param text 要匹配的文字
     * @return 转换后的正则表达式
     */
    protected String convertToRegEx(String text) {
    	if(text == null) return null;
    	if(text == "") return "";
    	
    	if(text.startsWith("glob:")
    			|| text.startsWith("regex:")) 
    		return text;
    	
    	StringBuilder sb = new StringBuilder("regex:");
    	for(int i = 0; i < text.length(); i++) {
    		sb.append(text.charAt(i));
    		if(i < text.length()-1) {
    			sb.append("[\\s　]*");
    		}
    	}
    	return sb.toString();
    }
    
    /**
     * 等待当前页面中出现特定文字, 该方法将在文字出现或超时后返回,超时后将导致测试用例失败
     * @param text 等待出现的页面文字,该文字不会转换为glob模式,因此不会匹配页面文字中的空格
     * @param timeout 超时时间,以毫秒计算
     */
    public void waitForAppearanceOfText(String text, long timeout) {
    	long end = System.currentTimeMillis() + timeout;
    	boolean succeed = false;
		while(System.currentTimeMillis() < end) {
			if(selenium.isTextPresent(text)) {
				succeed = true;
				break;
			}
		}
		if(!succeed) 
			fail("等待页面文字{" + text + "}渲染超时(" + timeout + "ms)");    	    	
    }
    
    /**
     * 等待当前页面中特定文字的消失, 该方法将在文字消失或超时后返回,超时后将导致测试用例失败
     * @param text 等待消失的页面文字,该文字不会转换为glob模式,因此不会匹配页面文字中的空格
     * @param timeout 超时时间,以毫秒计算
     */
    public void waitForDisappearanceOfText(String text, long timeout) {
    	long end = System.currentTimeMillis() + timeout;
    	boolean succeed = false;
		while(System.currentTimeMillis() < end) {
			if(!selenium.isTextPresent(text)) {
				succeed = true;
				break;
			}
		}
		if(!succeed) 
			fail("等待页面文字{" + text + "}消失超时(" + timeout + "ms)");    	    	
    }
    
    /**
     * 等待当前页面中出现指定的页面元素, 该方法将在元素出现或超时后返回,超时后将导致测试用例失败
     * @param locator 页面元素定位信息
     * @param timeout 超时时间,以毫秒计算
     */
    public void waitForAppearanceOfElement(String locator, long timeout) {
    	long end = System.currentTimeMillis() + timeout;
    	boolean succeed = false;
		while(System.currentTimeMillis() < end) {
			if(selenium.isElementPresent(locator)) {
				succeed = true;
				break;
			}
		}
		if(!succeed) 
			fail("等待页面元素{" + locator + "}渲染超时(" + timeout + "ms)");    	    	
    }
    
    /**
     * 等待当前页面中指定页面元素的消失, 该方法将在元素消失或超时后返回,超时后将导致测试用例失败
     * @param locator 页面元素定位信息
     * @param timeout 超时时间,以毫秒计算
     */
    public void waitForDisappearanceOfElement(String locator, long timeout) {
    	long end = System.currentTimeMillis() + timeout;
    	boolean succeed = false;
		while(System.currentTimeMillis() < end) {
			if(!selenium.isElementPresent(locator)) {
				succeed = true;
				break;
			}
		}
		if(!succeed) 
			fail("等待页面元素{" + locator + "}消失超时(" + timeout + "ms)");    	    	
    }
    
    /**
     * 验证当前页面上是否存在特定的文字
     * @param text 指定的文字,改文字将会被转换为glob模式以匹配页面上文字中间的空格
     * @param pageInfo 对当前页面的文字性描述,推荐使用onPage("myPage")增强测试代码的可读性
     */
    public void verifyPresenceOfText(String text, String pageInfo) {
		verifyTrue(selenium.isTextPresent(convertToRegEx(text)), 
				"页面{" + pageInfo + "}中未能匹配文字{" + text + "}");    	
    }
    
    /**
     * 验证当前页面上是否存在多个特定的文字
     * @param texts 指定文字组成的数组,每个指定的文字将会被转换为glob模式以匹配页面上文字中间的空格
     * @param pageInfo 对当前页面的文字性描述,推荐使用onPage("myPage")增强测试代码的可读性
     */
    public void verifyPresenceOfTexts(String[] texts, String pageInfo) {
		for(String text : texts) {
			verifyPresenceOfText(text, pageInfo);
		}

    }
    
    /**
     * 增强测试代码语义和可读性的函数，直接返回传入的页面描述
     * @param pageInfo 页面描述文字
     * @return 页面描述文字
     */
    public String onPage(String pageInfo) {
    	return pageInfo;
    }
    
    /**
     * 判定当前页面的Title是否为指定的值,判定失败将引起测试用例失败
     * @param title 指定的页面Title文字
     * @param pageInfo 对当前页面的文字性描述,推荐使用onPage("myPage")增强测试代码的可读性
     */
    public void assertPageTitle(String title, String pageInfo) {
    	assertEquals("页面{" + pageInfo +"}的Title标题不正确", 
    			title, selenium.getTitle());
    }
    
    
}
